/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package ai.backbrop;

import ai.*;
import ai.gui.ImageLabel;
import ai.gui.Image;
import ai.FloatVectorImage;
import ai.io.DataSource.Data;
import java.awt.Dimension;
import java.util.Observable;
import java.util.Vector;
import uk.ac.bath.util.Tweakable;

/**
 *
 * @author pjl
 */
public class BackPropBrain extends AbstractBrain {


    BackPropF bp;
    int layerSizes[];
 //   private boolean debug=true;
  

    public BackPropBrain(Dimension d, Dimension dLab,int hidden[],double beta,double alpha) {
        super(d,dLab,"Back Propagation");

   

        layerSizes = new int[2+hidden.length];
        
        layerSizes[0]=nPixel;
        for (int i=1;i<=hidden.length;i++) {
            layerSizes[i]=hidden[i-1];
        }
        
        layerSizes[layerSizes.length-1]=nLabel;

        // Creating the net
        bp = new BackPropF(layerSizes, beta, alpha,rand);

        for (int i = 0; i < layerSizes[1]; i++) {
            imagination.add(new WeightVectorImage(bp.weight[1][i], d, "pre" + i));
        }

    }

    public String outString() {
        float out[] = bp.output();
        String ret = "";
        for (int i = 0; i < layerSizes[layerSizes.length - 1]; i++) {
            ret += "|" + i + ":" + String.format("%3.2f ", out[i]);
        }
        return ret;
    }

    public void fire(Data data) {

        bp.ffwd(data.image);
     
        loadOut(data);
        setChanged();
    // return bp.output();
    }

    public void setTrain(Data data) {
        bp.bpgt(data.image, data.label);
     
        loadOut(data);
        setChanged();
    }

    /**
     * copy cached result into result supplied by caller
     * 
     * @param result   overwritten with current cached result
     */
    public synchronized void getLatestResult(Result res) {
        if (this.result == null) {
            return;
        }
        System.arraycopy(this.result.in.label, 0, res.in.label, 0, nLabel);
        System.arraycopy(this.result.in.image, 0, res.in.image, 0, nPixel);

        System.arraycopy(this.result.out.label, 0, res.out.label, 0, nLabel);
        System.arraycopy(this.result.out.image, 0, res.out.image, 0, nPixel);

    }

    private synchronized void loadOut(Data data) {
        //      System.arraycopy(bp.output(), nPixel,result.out.label, 0, nLabel);
        System.arraycopy(bp.output(), 0, result.out.label, 0, nLabel);
        System.arraycopy(data.label, 0, result.in.label, 0, nLabel);
        System.arraycopy(data.image, 0, result.in.image, 0, nPixel);
    }

    public Vector<Tweakable> getTweaks() {
        return bp.getTweaks();
    }
    
    public void dump() {
        bp.dump();
    }
    
}
